
<template>
	<fe-page title="角色详情" @back="goBack">
		<div class="role-div" v-loading="loading">
			<div class="role-left">
        <div class="role-title">
          <el-icon size="20"><UserFilled /></el-icon>
          <span class="name">{{ form.roleName }}</span>
        </div>
        <div class="role-des">角色描述：{{ form.roleDesc || '--' }}</div>
      </div>
      <div class="role-right role-des">包含 {{ userTotal }} 人</div>
		</div>
		<el-tabs>
			<el-tab-pane label="操作权限">
				<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
				<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
				<el-checkbox v-model="menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
				<el-tree class="tree-border tree-box tree-menu"
					:data="menuOptions"
					show-checkbox
					ref="menuRef"
					node-key="menuId"
					:check-strictly="!menuCheckStrictly"
					empty-text="加载中，请稍候"
					:props="{ label: 'menuName', children: 'children', class: customNodeClass }"
				></el-tree>
				<div class="pane-foot">
					<el-button type="primary" @click="handleMenu" v-hasPermi="['system:role:edit']">保存</el-button>
				</div>
			</el-tab-pane>
			<el-tab-pane label="数据权限">
        <div class="data-scope">
          <div class="scope-title"><span class="name">数据权限设置</span><span class="tip">（设置该角色的用户可以操作的数据的范围）</span></div>
          <el-checkbox-group v-model="dataScope" @change="dataScopeSelectChange" class="column-checkbox">
            <el-checkbox v-for="dict in sys_data_perm" :key="dict.value" :value="JSON.parse(dict.value)">
              <span class="name">{{ dict.label }}</span><span class="tip">{{ deptTip[dict.value] }}</span>
            </el-checkbox>
          </el-checkbox-group>
        </div>
        <div class="data-box" v-show="dataScope.includes(8)">
          <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
          <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
          <el-checkbox v-model="deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
          <el-tree
            class="tree-border tree-box tree-menu"
            :data="deptOptions"
            show-checkbox
            default-expand-all
            ref="deptRef"
            node-key="deptId"
            :check-strictly="!deptCheckStrictly"
            empty-text="加载中，请稍候"
            :props="{ label: 'deptName', children: 'children' }"
          ></el-tree>
        </div>
        <div class="pane-foot">
					<el-button type="primary" @click="handleData" v-hasPermi="['system:role:edit']">保存</el-button>
				</div>
			</el-tab-pane>
			<el-tab-pane label="字段权限">
        <ul v-infinite-scroll="lowerTable" class="field-box">
          <el-collapse @change="handleTable">
            <el-collapse-item v-for="item in tableList" :key="item.tableName" :title="item.tableComment" :name="item.tableName">
              <el-row :gutter="16" class="field-list" v-loading="columnLoading === item.tableName">
                <el-col v-for="column in item.fieldList" :key="column.colName" :sm="12" :lg="6" class="field-item">
                  <span class="column-name">{{ column.colComment }}</span>
                  <el-select v-model="column.visibility" placeholder="可见性" style="width: 88px" @change="changeVisibility($event, item.tableName, column.colName)">
                    <el-option v-for="dict in sys_field_perm" :key="dict.value" :label="dict.label" :value="JSON.parse(dict.value)" />
                  </el-select>
                </el-col>
              </el-row>
            </el-collapse-item>
          </el-collapse>
          <p v-if="tableLoading">加载中</p>
        </ul>
			</el-tab-pane>
			<el-tab-pane label="成员列表">
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" icon="Plus"	@click="handleUserAdd" v-hasPermi="['system:dept:add']">添加人员</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" icon="Delete" @click="cancelAuthUser" v-hasPermi="['system:dept:add']">批量删除</el-button>
          </el-col>
          <right-toolbar :search="false" @queryTable="getUserList"></right-toolbar>
        </el-row>
        <el-table border v-loading="userLoading" :data="userList" @selection-change="handleSelectionChange">
          <el-table-column type="selection" width="55" align="center" />
          <el-table-column prop="username" label="账号" width="150" show-overflow-tooltip />
          <el-table-column prop="nickname" label="姓名" width="150" show-overflow-tooltip />
          <el-table-column prop="deptName" label="公司" show-overflow-tooltip></el-table-column>
          <el-table-column prop="createTime" label="创建时间" width="160">
            <template #default="scope">
              <span>{{ parseTime(scope.row.createTime) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" width="80" class-name="small-padding fixed-width" fixed="right">
            <template #default="scope">
              <el-button link type="danger" icon="Delete" @click="cancelAuthUser(scope.row)" v-hasPermi="['system:dept:remove']">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <pagination v-show="userTotal > 0" :total="userTotal" v-model:page="userParams.current" v-model:limit="userParams.size" @pagination="getUserList" />

        <select-user ref="selectRef" :roleId="userParams.roleId" :roleName="form.roleName" @ok="handleUserQuery" />
			</el-tab-pane>
		</el-tabs>
	</fe-page>
</template>

<script setup name="RoleView">
import { getRole, addAuth, updateRole, listTable, listColumn, updateColumn, authUserCancel } from "@/api/system/role"
import { listMenu } from "@/api/system/menu"
import { listDept } from "@/api/system/dept"
import { listUser } from "@/api/system/user"
import selectUser from "./selectUser"

const route = useRoute()
const { proxy } = getCurrentInstance()
const { sys_data_perm, sys_field_perm } = proxy.useDict("sys_data_perm", 'sys_field_perm')

const loading = ref(true)
const roleId = route.params && route.params.roleId
const form = ref({})
const menuOptions = ref([])
const menuExpand = ref(false)
const menuNodeAll = ref(false)
const menuCheckStrictly = ref(true)
const menuRef = ref(null)
const dataScope = ref([16])
const deptExpand = ref(true)
const deptNodeAll = ref(false)
const deptCheckStrictly = ref(true)
const deptOptions = ref([])
const deptRef = ref(null)
const deptTip = {
  '1': "只能操作自己和下属的数据",
  '4': "能操作自己、下属、和自己所属公司的数据",
  '2': "所属公司及下属公司 能操作自己、下属和自己所属公司及其子公司的数据",
  '16': "能操作全公司的数据",
  '8': "自定义数据权限"
}
const tableLoading = ref(true)
const columnLoading = ref('')
const tableList = ref([])
const tableParams = reactive({
  current: 1,
  size: 20,
  roleId,
})
const tableTotal = ref(0)
const userLoading = ref(false)
const userParams = reactive({
  current: 1,
  size: 20,
  roleId,
})
const userList = ref([])
const userTotal = ref(0)
const users = ref([])
const multiple = ref(true)
const customNodeClass = (data, node) => node.isLeaf ? 'is-leaf' : ''

function getInfo() {
	loading.value = true
	getRole(roleId).then(res => {
		let result = res.result || {}
		form.value = result
    dataScope.value = result.dataPerm ? [result.dataPerm] : []
		loading.value = false
    nextTick(() => {
      setTimeout(() => {
        let menuArr = result.menuIds || []
        menuArr.forEach((v) => {
          menuRef.value.setChecked(v, true, false)
        })
        let dataArr = result.dataScope? result.dataScope.split(',') : []
        dataArr.forEach((v) => {
          deptRef.value.setChecked(v, true, false)
        })
      }, 500)
    })
  })
}

function getMenuTree() {
  listMenu({ size: -1 }).then(response => {
    const result = response.result || {}
    let data = proxy.handleTree(result.records, "menuId")
    menuOptions.value = data
  })
}

function getMenuAllCheckedKeys() {
  // 目前被选中的菜单节点
  let checkedKeys = menuRef.value.getCheckedKeys()
  // 半选中的菜单节点
  let halfCheckedKeys = menuRef.value.getHalfCheckedKeys()
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
  return checkedKeys
}

function handleMenu() {
	let menuIds = getMenuAllCheckedKeys()
  addAuth({roleId, menuIds}).then(response => {
		proxy.$modal.msgSuccess("保存成功")
		getInfo()
	})
}

function getDeptTree() {
  return listDept({ size: -1, disable: false }).then(response => {
    const result = response.result || {}
    let data = proxy.handleTree(result.records, "deptId")
    deptOptions.value = data
  })
}

function dataScopeSelectChange(value) {
  if(value.length > 1) dataScope.value.shift()
  if (!value.includes(8)) {
    nextTick(() => {
      deptRef.value.setCheckedKeys([])
    })
  }
}

function getDeptAllCheckedKeys() {
  // 目前被选中的公司节点
  let checkedKeys = deptRef.value.getCheckedKeys()
  // 半选中的公司节点
  let halfCheckedKeys = deptRef.value.getHalfCheckedKeys()
  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
  return checkedKeys
}

function handleData() {
  let dataPerm = dataScope.value[0] || 0
  let dataIds = getDeptAllCheckedKeys().join(',')
  updateRole({roleId, dataPerm, dataScope: dataIds}).then(response => {
		proxy.$modal.msgSuccess("保存成功")
		getInfo()
	})
}

function handleCheckedTreeExpand(value, type) {
  if (type == "menu") {
    let treeList = menuOptions.value
    for (let i = 0; i < treeList.length; i++) {
      menuRef.value.store.nodesMap[treeList[i].menuId].expanded = value
    }
  } else if (type == "dept") {
    let treeList = deptOptions.value
    for (let i = 0; i < treeList.length; i++) {
      deptRef.value.store.nodesMap[treeList[i].deptId].expanded = value
    }
  }
}

function handleCheckedTreeNodeAll(value, type) {
  if (type == "menu") {
    menuRef.value.setCheckedNodes(value ? menuOptions.value : [])
  } else if (type == "dept") {
    deptRef.value.setCheckedNodes(value ? deptOptions.value : [])
  }
}

function handleCheckedTreeConnect(value, type) {
  if (type == "menu") {
    menuCheckStrictly.value = value ? true : false
  } else if (type == "dept") {
    deptCheckStrictly.value = value ? true : false
  }
}

function getTable() {
  tableLoading.value = true
  tableParams.current = 1
  listTable(tableParams).then(response => {
    tableLoading.value = false
    const result = response.result || {}
    tableList.value = result.records || []
    tableTotal.value = Number(result.total)
  })
}

function lowerTable() {
  if(tableList.value.length < tableTotal.value) {
    tableLoading.value = true
    tableParams.current ++
    listTable(tableParams).then(response => {
      tableLoading.value = false
      const result = response.result || {}
      let data = result.records || []
      tableTotal.value = Number(result.total)
      tableList.value.push(...data)
    })
  }
}
function handleTable(arr) {
  arr.forEach(key => {
    let curTable = tableList.value.find(v => v.tableName === key)
    if(!curTable.fieldList) {
      columnLoading.value = key
      listColumn({tableName: key, roleId}).then(res => {
        columnLoading.value = ''
        const result = res.result || []
        curTable.fieldList = result
      }).catch(() => columnLoading.value = '')
    }
  })
}

function changeVisibility(val, tableName, colName) {
  columnLoading.value = tableName
  updateColumn({roleId, tableName, colName, visibility: val}).then(response => {
    columnLoading.value = ''
		proxy.$modal.msgSuccess("修改成功")
	}).catch(() => columnLoading.value = '')
}

function getUserList() {
  userLoading.value = true
  listUser(userParams).then(response => {
    const result = response.result || {}
    userList.value = result.records || []
    userTotal.value = Number(result.total)
    userLoading.value = false
  })
}

function handleUserQuery() {
  userParams.current = 1
  getUserList()
}

function handleSelectionChange(selection) {
  users.value = selection
  multiple.value = !selection.length
}

function handleUserAdd() {
  proxy.$refs["selectRef"].show()
}

function cancelAuthUser(row) {
  const userIds = row.userId? [row.userId] : users.value.map(item => item.userId)
  const userNames = row.nickname || users.value.map(item => item.nickname)
  proxy.$modal.confirm('是否确认从该角色下删除成员姓名为"' + userNames + '"的成员?').then(function () {
    return authUserCancel(roleId, userIds)
  }).then(() => {
    getUserList()
    proxy.$modal.msgSuccess("删除成功")
  }).catch(() => {})
}

function goBack() {
  const obj = { path: "/system/role" }
  proxy.$tab.closeOpenPage(obj)
}

getMenuTree()
getDeptTree()
getTable()
getUserList()
onMounted(() => {
  getInfo()
})
</script>

<style lang="scss" scoped>
:deep(.el-tabs) {
  height: calc(100% - 79px);
  .el-tab-pane{
    height: 100%;
  }
}
.role-div{
	padding: 14px 16px;
	background-color: var(--el-color-primary-light-9);
	display: flex;
  align-items: center;
  .role-left{
    flex: 1;
    display: flex;
	  flex-direction: column;
	  gap: 8px;
  }
  .role-right{
    flex-shrink: 0;
  }
	.role-title{
		display: flex;
		align-items: center;
		gap: 8px;
		color: var(--el-color-primary);
		.name{
			font-size: var(--el-font-size-large);
      font-weight: 600;
      color: #303133;
		}
	}
	.role-des{
		color: var(--el-color-info);
	}
}
.tree-menu{
  height: calc(100% - 85px);
  overflow-y: auto;
}
.data-scope{
  .scope-title{
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
    .name{
      font-size: var(--el-font-size-medium);
      font-weight: 600;
      color: var(--el-text-color-primary);
    }
    .tip{
      color: var(--el-color-info);
    }
  }
  :deep(.el-checkbox) {
		display: block;
    .el-checkbox__label{
      display: inline-flex;
      align-items: center;
      gap: 24px;
      .name{
        width: 126px;
      }
      .tip{
        font-size: var(--el-font-size-extra-small);
        color: var(--el-color-info);
      }
    }
	}
}
.data-box{
  height: calc(100% - 245px);
}
.field-box{
  height: 100%;
  padding: 0;
  margin: 0;
  list-style: none;
  overflow-y: auto;
  :deep(.el-collapse-item__header) {
    background-color: var(--el-color-info-light-9);
    padding: 0px 16px;
    font-weight: 600;
  }
  .field-list{
    padding: 16px 16px 0;
    min-height: 64px;
  }
  .field-item{
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    overflow: hidden;
    margin-bottom: 12px;
    .column-name{
      width: 120px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}
.tree-box{
  padding: 16px;
	:deep(.is-leaf) {
		display: inline-block;
	}
}
.pane-foot{
  padding-top: 16px;
	display: flex;
	justify-content: center;
	align-items: center;
	background-color: var(--el-bg-color);
}
</style>